// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.eva.android.widget;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.eva.android.ToolKits;
import com.x52im.rbchat.IMClientManager;
import com.x52im.rbchat.MyApplication;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

/**
 * 一个Fragment的封装根类，对各种方法进行了规范化封装和约定等。
 *
 * @author JackJiang
 * @since 8.0
 */
public abstract class BaseFragment extends Fragment {

    private final static String TAG = BaseFragment.class.getSimpleName();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // onCreate后要调用的逻辑
        onCreateAfter();
    }

    /**
     * 本方法由父类的 {@link #onCreate(Bundle)} 调用，子类可在此方法中实现
     * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 方法被调用前的一些逻辑。
     * 
     * @see #onCreate(Bundle)
     */
    protected void onCreateAfter(){ }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 初始化传递进来的数据
        Bundle bundle = getArguments();
        if (bundle != null) {
            initDataFromIntent(bundle);
        }
        // 初始化ui组件等
        View view = initViews(inflater, container);
        // 初始化各种ui事件处理
        initListeners();
        // 要做的额外事情
        initOthers();
        return view;
    }

    /**
     * <p>
     * 解析从Intent中传过来的可能的数据本方法中实现.
     * 例如从上一个activity中传过来的数据，本方法被 {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}调用。
     *
     * <b>本方法默认什么也不做.</b>
     * </p>
     *
     * @see #onCreateView(LayoutInflater, ViewGroup, Bundle)
     */
    protected void initDataFromIntent(Bundle savedInstanceState) {
    }

    /**
     * 本方法由父类的 {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 调用，子类可在此方法中实现ui的初始化。
     *
     * @see #onCreateView(LayoutInflater, ViewGroup, Bundle)
     */
    protected abstract View initViews(@NonNull LayoutInflater inflater, @Nullable ViewGroup container);

    /**
     * 本方法由父类的 {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 调用，子类可在此方法中实现ui的事件监听器初始化。
     *
     * @see #onCreateView(LayoutInflater, ViewGroup, Bundle)
     */
    protected void initListeners(){}

    /**
     * 本方法由父类的 {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 调用，子类可在此方法中实现ui的初始化的其它额外逻辑。
     *
     * @see #onCreateView(LayoutInflater, ViewGroup, Bundle)
     */
    protected void initOthers(){}

    /**
     * 一个方便的 getResources().getString(id) 方法封装。
     *
     * @param id 资源id
     * @return 字符串
     * @see #getResources()
     * @see #getString(int)
     */
    public String $$(int id) {
        return this.getResources().getString(id);
    }

    /**
     * 资源字符串国际化。
     *
     * @param messageFormatPatternResId 资源字符串，字符串内容通常形如："视频会话发送失败 t0 {0}({1},{2})"
     * @param arguments 对应于messageFormatPatternResId中的占位符
     * @return 返回格式化后的字符串
     */
    private String i18n(int messageFormatPatternResId, Object... arguments) {
        return ToolKits.i18n(getContext(), messageFormatPatternResId, arguments);
    }

    /**
     * 一个方便简短的获取本地用户信息的方法。
     *
     * @return 如果读取成功则返回本地用户信息对象，否则返回null
     */
    protected RosterElementEntity lu() {
        try{
            return MyApplication.getInstance2().getIMClientManager().getLocalUserInfo();
        }
        catch (Exception e){
            Log.w(TAG, e);
        }
        return null;
    }

    /**
     * 一个方便简短的获取IMClientManager全局对象引用的方法。
     *
     * @return 如果读取成功则返回对象，否则返回null
     */
    protected IMClientManager imc(){
        return MyApplication.getInstance2().getIMClientManager();
    }

    /**
     * getContext()的简短形式，美化调用代码。
     *
     * @return 返回上下文对象
     */
    public Context c(){
        return getContext();
    }

    /**
     * getActivity()的简短形式，美化调用代码。
     *
     * @return 返回Activity对象
     */
    public Activity a(){
        return getActivity();
    }

    /**
     * 本方法将接收由父Activity传递进来的长按事件（本方法默认什么也不做）。
     * 由于Fragment中并没有Activity中的长按事件，所以只能通过Activity主动调用本方法以便传递进来。
     *
     * @param ev 长按事件
     * @return 见Activity文档
     */
    public boolean dispatchTouchEvent(MotionEvent ev){
        // 默认什么也不做
        return false;
    }

    /**
     * 更新RecyleView可视区内的item显示。
     *
     * @param layoutManager RecyleView的布局管理器
     * @param adapter RecyleView对应的adapter对象
     */
    public void notifyVisibleDataSetChanged(LinearLayoutManager layoutManager, RecyclerView.Adapter<RecyclerView.ViewHolder> adapter){
        try {
            if (layoutManager != null && adapter != null) {
                int start = layoutManager.findFirstVisibleItemPosition();
                int end = layoutManager.findLastVisibleItemPosition();
                // 注意：第3个payload参数不应为null，否则将导致局部刷新后图片会闪一下的问题，填任意值即可
                // 资料：https://blog.csdn.net/Ghost_tal/article/details/82790359
                //      https://blog.csdn.net/jdsjlzx/article/details/52893469/
                adapter.notifyItemRangeChanged(start, end - start + 1, "any");
            } else {
                Log.w(TAG, "无效的参数：layoutManager=" + layoutManager + "， adapter=" + adapter);
            }
        }
        catch (Exception e){
            Log.w(TAG, e);
        }
    }
}
